{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "97db0caa-bb65-49cf-acb7-34821a8b9e7f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "require 'httparty'\n",
    "require 'dotenv'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9ce19b3c-4f63-475a-8718-dc635a76be79",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":submit_answer"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class AoCClient\n",
    "    include HTTParty\n",
    "    base_uri 'https://adventofcode.com'\n",
    "\n",
    "    def initialize(year, day, session)\n",
    "        @year = year\n",
    "        @day = day\n",
    "        @options = { headers: { cookie: \"session=#{session}\" } }\n",
    "    end\n",
    "\n",
    "    def get_input()\n",
    "        self.class.get(\"/#{@year}/day/#{@day}/input\", @options)\n",
    "    end\n",
    "\n",
    "    def submit_answer(level, answer)\n",
    "        self.class.post(\"/#{@year}/day/#{@day}/answer\", {**@options, body: {\n",
    "            level: level,\n",
    "            answer: answer,\n",
    "        }})\n",
    "    end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2b279352-48e9-4102-b447-95ba22e132bf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "year = 2021\n",
    "day = 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "cefef45c-5634-47a9-98c4-5085ab9fd4f1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Input fetched from adventofcode.com\""
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "session = Dotenv.load(\"../../.env\")[\"AOC_SESSION\"]\n",
    "client = AoCClient.new(year, day, session)\n",
    "input = client.get_input()\n",
    "\"Input fetched from adventofcode.com\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "9ad0d65b-11e2-4e95-9619-11b6a812cbfd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"00100\\n11110\\n10110\\n10111\\n10101\\n01111\\n00111\\n11100\\n10000\\n11001\\n00010\\n01010\""
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sample = \"00100\n",
    "11110\n",
    "10110\n",
    "10111\n",
    "10101\n",
    "01111\n",
    "00111\n",
    "11100\n",
    "10000\n",
    "11001\n",
    "00010\n",
    "01010\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "429c8fd4-9a14-4b21-85ed-62293dbabe2b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":part_one"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def part_one(input)\n",
    "    codes = input.split(\"\\n\").filter {|x| x.length > 0}\n",
    "    n = codes.length\n",
    "    m = codes[0].length\n",
    "    nums = codes.map {|x| x.to_i(base = 2)}\n",
    "    \n",
    "    x = (0..m-1).to_a.reverse.map { |i|\n",
    "        if nums.count {|num| (num & (1 << i)) > 0} >= nums.count {|num| (num & (1 << i)) == 0}\n",
    "            1 << i\n",
    "        else\n",
    "            0\n",
    "        end\n",
    "    }.sum\n",
    "    \n",
    "    y = (0..m-1).to_a.reverse.map { |i|\n",
    "        if nums.count {|num| (num & (1 << i)) == 0} <= nums.count {|num| (num & (1 << i)) > 0}\n",
    "            0\n",
    "        else\n",
    "            1 << i\n",
    "        end\n",
    "    }.sum\n",
    "    \n",
    "    x * y\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "43a7a3bd-38b9-4cfb-a863-8f9692800b16",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "198"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "part_one(sample)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "798c1cf0-15de-40ab-8e35-d0faa9b8c7ee",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2967914"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "part_one_ans = part_one(input)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac58032c-dec9-4117-8d87-622204300c6a",
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit_answer(1, part_one_ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "20bd2fa3-e774-43d2-bd33-ff62ad7a022a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":part_two"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def major(nums, i)\n",
    "    if nums.length == 1\n",
    "        nums[0]\n",
    "    else\n",
    "        one = nums.filter {|x| (x & (1 << i)) > 0}\n",
    "        zero = nums.filter {|x| (x & (1 << i)) == 0}\n",
    "        if one.length >= zero.length\n",
    "            major(one, i - 1)\n",
    "        else\n",
    "            major(zero, i - 1)\n",
    "        end\n",
    "    end\n",
    "end\n",
    "\n",
    "def minor(nums, i)\n",
    "    if nums.length == 1\n",
    "        nums[0]\n",
    "    else\n",
    "        one = nums.filter {|x| (x & (1 << i)) > 0}\n",
    "        zero = nums.filter {|x| (x & (1 << i)) == 0}\n",
    "        if zero.length <= one.length\n",
    "            minor(zero, i - 1)\n",
    "        else\n",
    "            minor(one, i - 1)\n",
    "        end\n",
    "    end\n",
    "end\n",
    "\n",
    "def part_two(input)\n",
    "    codes = input.split(\"\\n\").filter {|x| x.length > 0}\n",
    "    m = codes[0].length\n",
    "    nums = codes.map {|x| x.to_i(base = 2)}\n",
    "    major(nums, m - 1) * minor(nums, m - 1)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "62b8aca8-7f06-49ed-824a-a32631e18156",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "230"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "part_two(sample)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "fb60cee4-6cd7-47b6-a400-9ed6abea2e2c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7041258"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "part_two_ans = part_two(input)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3802cc9-1332-4a78-aea5-8b811ac4e035",
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit_answer(2, part_two_ans)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.7.0",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
